home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / util.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-11  |  35.1 KB  |  1,763 lines

  1. /* $RCSfile: util.c,v $$Revision: 4.0.1.4 $$Date: 91/11/11 16:48:54 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    util.c,v $
  9.  * Revision 4.0.1.4  91/11/11  16:48:54  lwall
  10.  * patch19: study was busted by 4.018
  11.  * patch19: added little-endian pack/unpack options
  12.  * 
  13.  * Revision 4.0.1.3  91/11/05  19:18:26  lwall
  14.  * patch11: safe malloc code now integrated into Perl's malloc when possible
  15.  * patch11: index("little", "longer string") could visit faraway places
  16.  * patch11: warn '-' x 10000 dumped core
  17.  * patch11: forked exec on non-existent program now issues a warning
  18.  * 
  19.  * Revision 4.0.1.2  91/06/07  12:10:42  lwall
  20.  * patch4: new copyright notice
  21.  * patch4: made some allowances for "semi-standard" C
  22.  * patch4: index() could blow up searching for null string
  23.  * patch4: taintchecks could improperly modify parent in vfork()
  24.  * patch4: exec would close files even if you cleared close-on-exec flag
  25.  * 
  26.  * Revision 4.0.1.1  91/04/12  09:19:25  lwall
  27.  * patch1: random cleanup in cpp namespace
  28.  * 
  29.  * Revision 4.0  91/03/20  01:56:39  lwall
  30.  * 4.0 baseline.
  31.  * 
  32.  */
  33. /*SUPPRESS 112*/
  34.  
  35. #include "EXTERN.h"
  36. #include "perl.h"
  37.  
  38. #if !defined(NSIG) || defined(M_UNIX) || defined(M_XENIX)
  39. #include <signal.h>
  40. #endif
  41.  
  42. #ifdef I_VFORK
  43. #  include <vfork.h>
  44. #endif
  45.  
  46. #ifdef I_VARARGS
  47. #  include <varargs.h>
  48. #endif
  49.  
  50. #ifdef I_FCNTL
  51. #  include <fcntl.h>
  52. #endif
  53. #ifdef I_SYS_FILE
  54. #  include <sys/file.h>
  55. #endif
  56.  
  57. #define FLUSH
  58.  
  59. #ifndef safemalloc
  60.  
  61. static char nomem[] = "Out of memory!\n";
  62.  
  63. /* paranoid version of malloc */
  64.  
  65. #ifdef DEBUGGING
  66. static int an = 0;
  67. #endif
  68.  
  69. /* NOTE:  Do not call the next three routines directly.  Use the macros
  70.  * in handy.h, so that we can easily redefine everything to do tracking of
  71.  * allocated hunks back to the original New to track down any memory leaks.
  72.  */
  73.  
  74. char *
  75. safemalloc(size)
  76. #ifdef MSDOS
  77. unsigned long size;
  78. #else
  79. MEM_SIZE size;
  80. #endif /* MSDOS */
  81. {
  82.     char *ptr;
  83. #ifndef STDMAC
  84.     char *malloc();
  85. #endif /* ! STDMAC */
  86.  
  87. #ifdef MSDOS
  88.     if (size > 0xffff) {
  89.         fprintf(stderr, "Allocation too large: %lx\n", size) FLUSH;
  90.         exit(1);
  91.     }
  92. #endif /* MSDOS */
  93. #ifdef DEBUGGING
  94.     if ((long)size < 0)
  95.     fatal("panic: malloc");
  96. #endif
  97.     ptr = malloc(size?size:1);    /* malloc(0) is NASTY on our system */
  98. #ifdef DEBUGGING
  99. #  ifndef I286
  100.     if (debug & 128)
  101.     fprintf(stderr,"0x%x: (%05d) malloc %d bytes\n",ptr,an++,size);
  102. #  else
  103.     if (debug & 128)
  104.     fprintf(stderr,"0x%lx: (%05d) malloc %d bytes\n",ptr,an++,size);
  105. #  endif
  106. #endif
  107.     if (ptr != Nullch)
  108.     return ptr;
  109.     else {
  110.     fputs(nomem,stderr) FLUSH;
  111.     exit(1);
  112.     }
  113.     /*NOTREACHED*/
  114. #ifdef lint
  115.     return ptr;
  116. #endif
  117. }
  118.  
  119. /* paranoid version of realloc */
  120.  
  121. char *
  122. saferealloc(where,size)
  123. char *where;
  124. #ifndef MSDOS
  125. MEM_SIZE size;
  126. #else
  127. unsigned long size;
  128. #endif /* MSDOS */
  129. {
  130.     char *ptr;
  131. #ifndef STDMAC
  132.     char *realloc();
  133. #endif /* ! STDMAC */
  134.  
  135. #ifdef MSDOS
  136.     if (size > 0xffff) {
  137.         fprintf(stderr, "Reallocation too large: %lx\n", size) FLUSH;
  138.         exit(1);
  139.     }
  140. #endif /* MSDOS */
  141.     if (!where)
  142.     fatal("Null realloc");
  143. #ifdef DEBUGGING
  144.     if ((long)size < 0)
  145.     fatal("panic: realloc");
  146. #endif
  147.     ptr = realloc(where,size?size:1);    /* realloc(0) is NASTY on our system */
  148. #ifdef DEBUGGING
  149. #  ifndef I286
  150.     if (debug & 128) {
  151.     fprintf(stderr,"0x%x: (%05d) rfree\n",where,an++);
  152.     fprintf(stderr,"0x%x: (%05d) realloc %d bytes\n",ptr,an++,size);
  153.     }
  154. #  else
  155.     if (debug & 128) {
  156.     fprintf(stderr,"0x%lx: (%05d) rfree\n",where,an++);
  157.     fprintf(stderr,"0x%lx: (%05d) realloc %d bytes\n",ptr,an++,size);
  158.     }
  159. #  endif
  160. #endif
  161.     if (ptr != Nullch)
  162.     return ptr;
  163.     else {
  164.     fputs(nomem,stderr) FLUSH;
  165.     exit(1);
  166.     }
  167.     /*NOTREACHED*/
  168. #ifdef lint
  169.     return ptr;
  170. #endif
  171. }
  172.  
  173. /* safe version of free */
  174.  
  175. void
  176. safefree(where)
  177. char *where;
  178. {
  179. #ifdef DEBUGGING
  180. #  ifndef I286
  181.     if (debug & 128)
  182.     fprintf(stderr,"0x%x: (%05d) free\n",where,an++);
  183. #  else
  184.     if (debug & 128)
  185.     fprintf(stderr,"0x%lx: (%05d) free\n",where,an++);
  186. #  endif
  187. #endif
  188.     if (where) {
  189.     /*SUPPRESS 701*/
  190.     free(where);
  191.     }
  192. }
  193.  
  194. #endif /* !safemalloc */
  195.  
  196. #ifdef LEAKTEST
  197.  
  198. #define ALIGN sizeof(long)
  199.  
  200. char *
  201. safexmalloc(x,size)
  202. int x;
  203. MEM_SIZE size;
  204. {
  205.     register char *where;
  206.  
  207.     where = safemalloc(size + ALIGN);
  208.     xcount[x]++;
  209.     where[0] = x % 100;
  210.     where[1] = x / 100;
  211.     return where + ALIGN;
  212. }
  213.  
  214. char *
  215. safexrealloc(where,size)
  216. char *where;
  217. MEM_SIZE size;
  218. {
  219.     return saferealloc(where - ALIGN, size + ALIGN) + ALIGN;
  220. }
  221.  
  222. void
  223. safexfree(where)
  224. char *where;
  225. {
  226.     int x;
  227.  
  228.     if (!where)
  229.     return;
  230.     where -= ALIGN;
  231.     x = where[0] + 100 * where[1];
  232.     xcount[x]--;
  233.     safefree(where);
  234. }
  235.  
  236. xstat()
  237. {
  238.     register int i;
  239.  
  240.     for (i = 0; i < MAXXCOUNT; i++) {
  241.     if (xcount[i] > lastxcount[i]) {
  242.         fprintf(stderr,"%2d %2d\t%ld\n", i / 100, i % 100, xcount[i]);
  243.         lastxcount[i] = xcount[i];
  244.     }
  245.     }
  246. }
  247.  
  248. #endif /* LEAKTEST */
  249.  
  250. /* copy a string up to some (non-backslashed) delimiter, if any */
  251.  
  252. char *
  253. cpytill(to,from,fromend,delim,retlen)
  254. register char *to;
  255. register char *from;
  256. register char *fromend;
  257. register int delim;
  258. int *retlen;
  259. {
  260.     char *origto = to;
  261.  
  262.     for (; from < fromend; from++,to++) {
  263.     if (*from == '\\') {
  264.         if (from[1] == delim)
  265.         from++;
  266.         else if (from[1] == '\\')
  267.         *to++ = *from++;
  268.     }
  269.     else if (*from == delim)
  270.         break;
  271.     *to = *from;
  272.     }
  273.     *to = '\0';
  274.     *retlen = to - origto;
  275.     return from;
  276. }
  277.  
  278. /* return ptr to little string in big string, NULL if not found */
  279. /* This routine was donated by Corey Satten. */
  280.  
  281. char *
  282. instr(big, little)
  283. register char *big;
  284. register char *little;
  285. {
  286.     register char *s, *x;
  287.     register int first;
  288.  
  289.     if (!little)
  290.     return big;
  291.     first = *little++;
  292.     if (!first)
  293.     return big;
  294.     while (*big) {
  295.     if (*big++ != first)
  296.         continue;
  297.     for (x=big,s=little; *s; /**/ ) {
  298.         if (!*x)
  299.         return Nullch;
  300.         if (*s++ != *x++) {
  301.         s--;
  302.         break;
  303.         }
  304.     }
  305.     if (!*s)
  306.         return big-1;
  307.     }
  308.     return Nullch;
  309. }
  310.  
  311. /* same as instr but allow embedded nulls */
  312.  
  313. char *
  314. ninstr(big, bigend, little, lend)
  315. register char *big;
  316. register char *bigend;
  317. char *little;
  318. char *lend;
  319. {
  320.     register char *s, *x;
  321.     register int first = *little;
  322.     register char *littleend = lend;
  323.  
  324.     if (!first && little > littleend)
  325.     return big;
  326.     if (bigend - big < littleend - little)
  327.     return Nullch;
  328.     bigend -= littleend - little++;
  329.     while (big <= bigend) {
  330.     if (*big++ != first)
  331.         continue;
  332.     for (x=big,s=little; s < littleend; /**/ ) {
  333.         if (*s++ != *x++) {
  334.         s--;
  335.         break;
  336.         }
  337.     }
  338.     if (s >= littleend)
  339.         return big-1;
  340.     }
  341.     return Nullch;
  342. }
  343.  
  344. /* reverse of the above--find last substring */
  345.  
  346. char *
  347. rninstr(big, bigend, little, lend)
  348. register char *big;
  349. char *bigend;
  350. char *little;
  351. char *lend;
  352. {
  353.     register char *bigbeg;
  354.     register char *s, *x;
  355.     register int first = *little;
  356.     register char *littleend = lend;
  357.  
  358.     if (!first && little > littleend)
  359.     return bigend;
  360.     bigbeg = big;
  361.     big = bigend - (littleend - little++);
  362.     while (big >= bigbeg) {
  363.     if (*big-- != first)
  364.         continue;
  365.     for (x=big+2,s=little; s < littleend; /**/ ) {
  366.         if (*s++ != *x++) {
  367.         s--;
  368.         break;
  369.         }
  370.     }
  371.     if (s >= littleend)
  372.         return big+1;
  373.     }
  374.     return Nullch;
  375. }
  376.  
  377. unsigned char fold[] = {
  378.     0,    1,    2,    3,    4,    5,    6,    7,
  379.     8,    9,    10,    11,    12,    13,    14,    15,
  380.     16,    17,    18,    19,    20,    21,    22,    23,
  381.     24,    25,    26,    27,    28,    29,    30,    31,
  382.     32,    33,    34,    35,    36,    37,    38,    39,
  383.     40,    41,    42,    43,    44,    45,    46,    47,
  384.     48,    49,    50,    51,    52,    53,    54,    55,
  385.     56,    57,    58,    59,    60,    61,    62,    63,
  386.     64,    'a',    'b',    'c',    'd',    'e',    'f',    'g',
  387.     'h',    'i',    'j',    'k',    'l',    'm',    'n',    'o',
  388.     'p',    'q',    'r',    's',    't',    'u',    'v',    'w',
  389.     'x',    'y',    'z',    91,    92,    93,    94,    95,
  390.     96,    'A',    'B',    'C',    'D',    'E',    'F',    'G',
  391.     'H',    'I',    'J',    'K',    'L',    'M',    'N',    'O',
  392.     'P',    'Q',    'R',    'S',    'T',    'U',    'V',    'W',
  393.     'X',    'Y',    'Z',    123,    124,    125,    126,    127,
  394.     128,    129,    130,    131,    132,    133,    134,    135,
  395.     136,    137,    138,    139,    140,    141,    142,    143,
  396.     144,    145,    146,    147,    148,    149,    150,    151,
  397.     152,    153,    154,    155,    156,    157,    158,    159,
  398.     160,    161,    162,    163,    164,    165,    166,    167,
  399.     168,    169,    170,    171,    172,    173,    174,    175,
  400.     176,    177,    178,    179,    180,    181,    182,    183,
  401.     184,    185,    186,    187,    188,    189,    190,    191,
  402.     192,    193,    194,    195,    196,    197,    198,    199,
  403.     200,    201,    202,    203,    204,    205,    206,    207,
  404.     208,    209,    210,    211,    212,    213,    214,    215,
  405.     216,    217,    218,    219,    220,    221,    222,    223,    
  406.     224,    225,    226,    227,    228,    229,    230,    231,
  407.     232,    233,    234,    235,    236,    237,    238,    239,
  408.     240,    241,    242,    243,    244,    245,    246,    247,
  409.     248,    249,    250,    251,    252,    253,    254,    255
  410. };
  411.  
  412. static unsigned char freq[] = {
  413.     1,    2,    84,    151,    154,    155,    156,    157,
  414.     165,    246,    250,    3,    158,    7,    18,    29,
  415.     40,    51,    62,    73,    85,    96,    107,    118,
  416.     129,    140,    147,    148,    149,    150,    152,    153,
  417.     255,    182,    224,    205,    174,    176,    180,    217,
  418.     233,    232,    236,    187,    235,    228,    234,    226,
  419.     222,    219,    211,    195,    188,    193,    185,    184,
  420.     191,    183,    201,    229,    181,    220,    194,    162,
  421.     163,    208,    186,    202,    200,    218,    198,    179,
  422.     178,    214,    166,    170,    207,    199,    209,    206,
  423.     204,    160,    212,    216,    215,    192,    175,    173,
  424.     243,    172,    161,    190,    203,    189,    164,    230,
  425.     167,    248,    227,    244,    242,    255,    241,    231,
  426.     240,    253,    169,    210,    245,    237,    249,    247,
  427.     239,    168,    252,    251,    254,    238,    223,    221,
  428.     213,    225,    177,    197,    171,    196,    159,    4,
  429.     5,    6,    8,    9,    10,    11,    12,    13,
  430.     14,    15,    16,    17,    19,    20,    21,    22,
  431.     23,    24,    25,    26,    27,    28,    30,    31,
  432.     32,    33,    34,    35,    36,    37,    38,    39,
  433.     41,    42,    43,    44,    45,    46,    47,    48,
  434.     49,    50,    52,    53,    54,    55,    56,    57,
  435.     58,    59,    60,    61,    63,    64,    65,    66,
  436.     67,    68,    69,    70,    71,    72,    74,    75,
  437.     76,    77,    78,    79,    80,    81,    82,    83,
  438.     86,    87,    88,    89,    90,    91,    92,    93,
  439.     94,    95,    97,    98,    99,    100,    101,    102,
  440.     103,    104,    105,    106,    108,    109,    110,    111,
  441.     112,    113,    114,    115,    116,    117,    119,    120,
  442.     121,    122,    123,    124,    125,    126,    127,    128,
  443.     130,    131,    132,    133,    134,    135,    136,    137,
  444.     138,    139,    141,    142,    143,    144,    145,    146
  445. };
  446.  
  447. void
  448. fbmcompile(str, iflag)
  449. STR *str;
  450. int iflag;
  451. {
  452.     register unsigned char *s;
  453.     register unsigned char *table;
  454.     register unsigned int i;
  455.     register unsigned int len = str->str_cur;
  456.     int rarest = 0;
  457.     unsigned int frequency = 256;
  458.  
  459.     Str_Grow(str,len+258);
  460. #ifndef lint
  461.     table = (unsigned char*)(str->str_ptr + len + 1);
  462. #else
  463.     table = Null(unsigned char*);
  464. #endif
  465.     s = table - 2;
  466.     for (i = 0; i < 256; i++) {
  467.     table[i] = len;
  468.     }
  469.     i = 0;
  470. #ifndef lint
  471.     while (s >= (unsigned char*)(str->str_ptr))
  472. #endif
  473.     {
  474.     if (table[*s] == len) {
  475. #ifndef pdp11
  476.         if (iflag)
  477.         table[*s] = table[fold[*s]] = i;
  478. #else
  479.         if (iflag) {
  480.         int j;
  481.         j = fold[*s];
  482.         table[j] = i;
  483.         table[*s] = i;
  484.         }
  485. #endif /* pdp11 */
  486.         else
  487.         table[*s] = i;
  488.     }
  489.     s--,i++;
  490.     }
  491.     str->str_pok |= SP_FBM;        /* deep magic */
  492.  
  493. #ifndef lint
  494.     s = (unsigned char*)(str->str_ptr);        /* deeper magic */
  495. #else
  496.     s = Null(unsigned char*);
  497. #endif
  498.     if (iflag) {
  499.     register unsigned int tmp, foldtmp;
  500.     str->str_pok |= SP_CASEFOLD;
  501.     for (i = 0; i < len; i++) {
  502.         tmp=freq[s[i]];
  503.         foldtmp=freq[fold[s[i]]];
  504.         if (tmp < frequency && foldtmp < frequency) {
  505.         rarest = i;
  506.         /* choose most frequent among the two */
  507.         frequency = (tmp > foldtmp) ? tmp : foldtmp;
  508.         }
  509.     }
  510.     }
  511.     else {
  512.     for (i = 0; i < len; i++) {
  513.         if (freq[s[i]] < frequency) {
  514.         rarest = i;
  515.         frequency = freq[s[i]];
  516.         }
  517.     }
  518.     }
  519.     str->str_rare = s[rarest];
  520.     str->str_state = rarest;
  521. #ifdef DEBUGGING
  522.     if (debug & 512)
  523.     fprintf(stderr,"rarest char %c at %d\n",str->str_rare, str->str_state);
  524. #endif
  525. }
  526.  
  527. char *
  528. fbminstr(big, bigend, littlestr)
  529. unsigned char *big;
  530. register unsigned char *bigend;
  531. STR *littlestr;
  532. {
  533.     register unsigned char *s;
  534.     register int tmp;
  535.     register int littlelen;
  536.     register unsigned char *little;
  537.     register unsigned char *table;
  538.     register unsigned char *olds;
  539.     register unsigned char *oldlittle;
  540.  
  541. #ifndef lint
  542.     if (!(littlestr->str_pok & SP_FBM)) {
  543.     if (!littlestr->str_ptr)
  544.         return (char*)big;
  545.     return ninstr((char*)big,(char*)bigend,
  546.         littlestr->str_ptr, littlestr->str_ptr + littlestr->str_cur);
  547.     }
  548. #endif
  549.  
  550.     littlelen = littlestr->str_cur;
  551. #ifndef lint
  552.     if (littlestr->str_pok & SP_TAIL && !multiline) {    /* tail anchored? */
  553.     if (littlelen > bigend - big)
  554.         return Nullch;
  555.     little = (unsigned char*)littlestr->str_ptr;
  556.     if (littlestr->str_pok & SP_CASEFOLD) {    /* oops, fake it */
  557.         big = bigend - littlelen;        /* just start near end */
  558.         if (bigend[-1] == '\n' && little[littlelen-1] != '\n')
  559.         big--;
  560.     }
  561.     else {
  562.         s = bigend - littlelen;
  563.         if (*s == *little && bcmp(s,little,littlelen)==0)
  564.         return (char*)s;        /* how sweet it is */
  565.         else if (bigend[-1] == '\n' && little[littlelen-1] != '\n'
  566.           && s > big) {
  567.             s--;
  568.         if (*s == *little && bcmp(s,little,littlelen)==0)
  569.             return (char*)s;
  570.         }
  571.         return Nullch;
  572.     }
  573.     }
  574.     table = (unsigned char*)(littlestr->str_ptr + littlelen + 1);
  575. #else
  576.     table = Null(unsigned char*);
  577. #endif
  578.     if (--littlelen >= bigend - big)
  579.     return Nullch;
  580.     s = big + littlelen;
  581.     oldlittle = little = table - 2;
  582.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insensitive? */
  583.     if (s < bigend) {
  584.       top1:
  585.         /*SUPPRESS 560*/
  586.         if (tmp = table[*s]) {
  587. #ifdef POINTERRIGOR
  588.         if (bigend - s > tmp) {
  589.             s += tmp;
  590.             goto top1;
  591.         }
  592. #else
  593.         if ((s += tmp) < bigend)
  594.             goto top1;
  595. #endif
  596.         return Nullch;
  597.         }
  598.         else {
  599.         tmp = littlelen;    /* less expensive than calling strncmp() */
  600.         olds = s;
  601.         while (tmp--) {
  602.             if (*--s == *--little || fold[*s] == *little)
  603.             continue;
  604.             s = olds + 1;    /* here we pay the price for failure */
  605.             little = oldlittle;
  606.             if (s < bigend)    /* fake up continue to outer loop */
  607.             goto top1;
  608.             return Nullch;
  609.         }
  610. #ifndef lint
  611.         return (char *)s;
  612. #endif
  613.         }
  614.     }
  615.     }
  616.     else {
  617.     if (s < bigend) {
  618.       top2:
  619.         /*SUPPRESS 560*/
  620.         if (tmp = table[*s]) {
  621. #ifdef POINTERRIGOR
  622.         if (bigend - s > tmp) {
  623.             s += tmp;
  624.             goto top2;
  625.         }
  626. #else
  627.         if ((s += tmp) < bigend)
  628.             goto top2;
  629. #endif
  630.         return Nullch;
  631.         }
  632.         else {
  633.         tmp = littlelen;    /* less expensive than calling strncmp() */
  634.         olds = s;
  635.         while (tmp--) {
  636.             if (*--s == *--little)
  637.             continue;
  638.             s = olds + 1;    /* here we pay the price for failure */
  639.             little = oldlittle;
  640.             if (s < bigend)    /* fake up continue to outer loop */
  641.             goto top2;
  642.             return Nullch;
  643.         }
  644. #ifndef lint
  645.         return (char *)s;
  646. #endif
  647.         }
  648.     }
  649.     }
  650.     return Nullch;
  651. }
  652.  
  653. char *
  654. screaminstr(bigstr, littlestr)
  655. STR *bigstr;
  656. STR *littlestr;
  657. {
  658.     register unsigned char *s, *x;
  659.     register unsigned char *big;
  660.     register int pos;
  661.     register int previous;
  662.     register int first;
  663.     register unsigned char *little;
  664.     register unsigned char *bigend;
  665.     register unsigned char *littleend;
  666.  
  667.     if ((pos = screamfirst[littlestr->str_rare]) < 0) 
  668.     return Nullch;
  669. #ifndef lint
  670.     little = (unsigned char *)(littlestr->str_ptr);
  671. #else
  672.     little = Null(unsigned char *);
  673. #endif
  674.     littleend = little + littlestr->str_cur;
  675.     first = *little++;
  676.     previous = littlestr->str_state;
  677. #ifndef lint
  678.     big = (unsigned char *)(bigstr->str_ptr);
  679. #else
  680.     big = Null(unsigned char*);
  681. #endif
  682.     bigend = big + bigstr->str_cur;
  683.     while (pos < previous) {
  684. #ifndef lint
  685.     if (!(pos += screamnext[pos]))
  686. #endif
  687.         return Nullch;
  688.     }
  689. #ifdef POINTERRIGOR
  690.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  691.     do {
  692.         if (big[pos-previous] != first && big[pos-previous] != fold[first])
  693.         continue;
  694.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  695.         if (x >= bigend)
  696.             return Nullch;
  697.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  698.             s--;
  699.             break;
  700.         }
  701.         }
  702.         if (s == littleend)
  703. #ifndef lint
  704.         return (char *)(big+pos-previous);
  705. #else
  706.         return Nullch;
  707. #endif
  708.     } while (
  709. #ifndef lint
  710.         pos += screamnext[pos]    /* does this goof up anywhere? */
  711. #else
  712.         pos += screamnext[0]
  713. #endif
  714.         );
  715.     }
  716.     else {
  717.     do {
  718.         if (big[pos-previous] != first)
  719.         continue;
  720.         for (x=big+pos+1-previous,s=little; s < littleend; /**/ ) {
  721.         if (x >= bigend)
  722.             return Nullch;
  723.         if (*s++ != *x++) {
  724.             s--;
  725.             break;
  726.         }
  727.         }
  728.         if (s == littleend)
  729. #ifndef lint
  730.         return (char *)(big+pos-previous);
  731. #else
  732.         return Nullch;
  733. #endif
  734.     } while (
  735. #ifndef lint
  736.         pos += screamnext[pos]
  737. #else
  738.         pos += screamnext[0]
  739. #endif
  740.         );
  741.     }
  742. #else /* !POINTERRIGOR */
  743.     big -= previous;
  744.     if (littlestr->str_pok & SP_CASEFOLD) {    /* case insignificant? */
  745.     do {
  746.         if (big[pos] != first && big[pos] != fold[first])
  747.         continue;
  748.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  749.         if (x >= bigend)
  750.             return Nullch;
  751.         if (*s++ != *x++ && fold[*(s-1)] != *(x-1)) {
  752.             s--;
  753.             break;
  754.         }
  755.         }
  756.         if (s == littleend)
  757. #ifndef lint
  758.         return (char *)(big+pos);
  759. #else
  760.         return Nullch;
  761. #endif
  762.     } while (
  763. #ifndef lint
  764.         pos += screamnext[pos]    /* does this goof up anywhere? */
  765. #else
  766.         pos += screamnext[0]
  767. #endif
  768.         );
  769.     }
  770.     else {
  771.     do {
  772.         if (big[pos] != first)
  773.         continue;
  774.         for (x=big+pos+1,s=little; s < littleend; /**/ ) {
  775.         if (x >= bigend)
  776.             return Nullch;
  777.         if (*s++ != *x++) {
  778.             s--;
  779.             break;
  780.         }
  781.         }
  782.         if (s == littleend)
  783. #ifndef lint
  784.         return (char *)(big+pos);
  785. #else
  786.         return Nullch;
  787. #endif
  788.     } while (
  789. #ifndef lint
  790.         pos += screamnext[pos]
  791. #else
  792.         pos += screamnext[0]
  793. #endif
  794.         );
  795.     }
  796. #endif /* POINTERRIGOR */
  797.     return Nullch;
  798. }
  799.  
  800. /* copy a string to a safe spot */
  801.  
  802. char *
  803. savestr(str)
  804. char *str;
  805. {
  806.     register char *newaddr;
  807.  
  808.     New(902,newaddr,strlen(str)+1,char);
  809.     (void)strcpy(newaddr,str);
  810.     return newaddr;
  811. }
  812.  
  813. /* same thing but with a known length */
  814.  
  815. char *
  816. nsavestr(str, len)
  817. char *str;
  818. register int len;
  819. {
  820.     register char *newaddr;
  821.  
  822.     New(903,newaddr,len+1,char);
  823.     (void)bcopy(str,newaddr,len);    /* might not be null terminated */
  824.     newaddr[len] = '\0';        /* is now */
  825.     return newaddr;
  826. }
  827.  
  828. /* grow a static string to at least a certain length */
  829.  
  830. void
  831. growstr(strptr,curlen,newlen)
  832. char **strptr;
  833. int *curlen;
  834. int newlen;
  835. {
  836.     if (newlen > *curlen) {        /* need more room? */
  837.     if (*curlen)
  838.         Renew(*strptr,newlen,char);
  839.     else
  840.         New(905,*strptr,newlen,char);
  841.     *curlen = newlen;
  842.     }
  843. }
  844.  
  845. #ifndef I_VARARGS
  846. /*VARARGS1*/
  847. char *
  848. mess(pat,a1,a2,a3,a4)
  849. char *pat;
  850. long a1, a2, a3, a4;
  851. {
  852.     char *s;
  853.     int usermess = strEQ(pat,"%s");
  854.     STR *tmpstr;
  855.  
  856.     s = buf;
  857. #ifdef macintosh
  858.     if (usermess) {
  859.     tmpstr = str_mortal(&str_undef);
  860.     str_set(tmpstr, "# ");
  861.     str_cat(tmpstr, (char*)a1);
  862.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  863.     }
  864.     else {
  865.         (void) sprintf(buf, "# ");
  866.         s += 2;
  867.     (void)sprintf(s,pat,a1,a2,a3,a4);
  868.     s += strlen(s);
  869.     }
  870. #else
  871.     if (usermess) {
  872.     tmpstr = str_mortal(&str_undef);
  873.     str_set(tmpstr, (char*)a1);
  874.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  875.     }
  876.     else {
  877.     (void)sprintf(s,pat,a1,a2,a3,a4);
  878.     s += strlen(s);
  879.     }
  880. #endif
  881.  
  882.     if (s[-1] != '\n') {
  883. #ifdef macintosh
  884.     if (last_in_stab &&
  885.         stab_io(last_in_stab) &&
  886.         stab_io(last_in_stab)->lines ) {
  887.         if (s[-1] != '.')
  888.             *s++ = '.';
  889.         (void)sprintf(s," Input from <%s>, line %ld",
  890.           last_in_stab == argvstab ? "" : stab_name(last_in_stab),
  891.           (long)stab_io(last_in_stab)->lines);
  892.         s += strlen(s);
  893.     }
  894.     if (curcmd->c_line) {
  895.         (void)sprintf(s,"\nFile \"%s\"; Line %ld",
  896.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  897.         s += strlen(s);
  898.     }
  899.     (void)strcpy(s,"\n");
  900. #else
  901.     if (curcmd->c_line) {
  902.         (void)sprintf(s," at %s line %ld",
  903.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  904.         s += strlen(s);
  905.     }
  906.     if (last_in_stab &&
  907.         stab_io(last_in_stab) &&
  908.         stab_io(last_in_stab)->lines ) {
  909.         (void)sprintf(s,", <%s> line %ld",
  910.           last_in_stab == argvstab ? "" : stab_name(last_in_stab),
  911.           (long)stab_io(last_in_stab)->lines);
  912.         s += strlen(s);
  913.     }
  914.     (void)strcpy(s,".\n");
  915. #endif
  916.     if (usermess)
  917.         str_cat(tmpstr,buf+1);
  918.     }
  919.     if (usermess)
  920.     return tmpstr->str_ptr;
  921.     else
  922.     return buf;
  923. }
  924.  
  925. /*VARARGS1*/
  926. fatal(pat,a1,a2,a3,a4)
  927. char *pat;
  928. long a1, a2, a3, a4;
  929. {
  930.     extern FILE *e_fp;
  931.     extern char *e_tmpname;
  932.     char *tmps;
  933.     char *message;
  934.  
  935.     message = mess(pat,a1,a2,a3,a4);
  936.     if (in_eval) {
  937.     str_set(stab_val(stabent("@",TRUE)),message);
  938.     tmps = "_EVAL_";
  939.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  940.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  941. #ifdef DEBUGGING
  942.         if (debug & 4) {
  943.         deb("(Skipping label #%d %s)\n",loop_ptr,
  944.             loop_stack[loop_ptr].loop_label);
  945.         }
  946. #endif
  947.         loop_ptr--;
  948.     }
  949. #ifdef DEBUGGING
  950.     if (debug & 4) {
  951.         deb("(Found label #%d %s)\n",loop_ptr,
  952.         loop_stack[loop_ptr].loop_label);
  953.     }
  954. #endif
  955.     if (loop_ptr < 0) {
  956.         in_eval = 0;
  957.         fatal("Bad label: %s", tmps);
  958.     }
  959.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  960.     }
  961.     fputs(message,stderr);
  962.     (void)fflush(stderr);
  963.     if (e_fp)
  964.     (void)UNLINK(e_tmpname);
  965.     statusvalue >>= 8;
  966.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  967. }
  968.  
  969. /*VARARGS1*/
  970. warn(pat,a1,a2,a3,a4)
  971. char *pat;
  972. long a1, a2, a3, a4;
  973. {
  974.     char *message;
  975.  
  976.     message = mess(pat,a1,a2,a3,a4);
  977.     fputs(message,stderr);
  978. #ifdef LEAKTEST
  979. #ifdef DEBUGGING
  980.     if (debug & 4096)
  981.     xstat();
  982. #endif
  983. #endif
  984.     (void)fflush(stderr);
  985. }
  986. #else
  987. /*VARARGS0*/
  988. char *
  989. mess(args)
  990. va_list args;
  991. {
  992.     char *pat;
  993.     char *s;
  994.     STR *tmpstr;
  995.     int usermess;
  996. #ifndef HAS_VPRINTF
  997. #ifdef CHARVSPRINTF
  998.     char *vsprintf();
  999. #else
  1000.     int vsprintf();
  1001. #endif
  1002. #endif
  1003.  
  1004. #ifdef lint
  1005.     pat = Nullch;
  1006. #else
  1007.     pat = va_arg(args, char *);
  1008. #endif
  1009.     s = buf;
  1010.     usermess = strEQ(pat, "%s");
  1011.     if (usermess) {
  1012.     tmpstr = str_mortal(&str_undef);
  1013.     str_set(tmpstr, va_arg(args, char *));
  1014.     *s++ = tmpstr->str_ptr[tmpstr->str_cur-1];
  1015.     }
  1016.     else {
  1017.     (void) vsprintf(s,pat,args);
  1018.     s += strlen(s);
  1019.     }
  1020.  
  1021.     if (s[-1] != '\n') {
  1022.     if (curcmd->c_line) {
  1023.         (void)sprintf(s," at %s line %ld",
  1024.           stab_val(curcmd->c_filestab)->str_ptr, (long)curcmd->c_line);
  1025.         s += strlen(s);
  1026.     }
  1027.     if (last_in_stab &&
  1028.         stab_io(last_in_stab) &&
  1029.         stab_io(last_in_stab)->lines ) {
  1030.         (void)sprintf(s,", <%s> line %ld",
  1031.           last_in_stab == argvstab ? "" : last_in_stab->str_magic->str_ptr,
  1032.           (long)stab_io(last_in_stab)->lines);
  1033.         s += strlen(s);
  1034.     }
  1035.     (void)strcpy(s,".\n");
  1036.     if (usermess)
  1037.         str_cat(tmpstr,buf+1);
  1038.     }
  1039.  
  1040.     if (usermess)
  1041.     return tmpstr->str_ptr;
  1042.     else
  1043.     return buf;
  1044. }
  1045.  
  1046. /*VARARGS0*/
  1047. fatal(va_alist)
  1048. va_dcl
  1049. {
  1050.     va_list args;
  1051.     extern FILE *e_fp;
  1052.     extern char *e_tmpname;
  1053.     char *tmps;
  1054.     char *message;
  1055.  
  1056. #ifndef lint
  1057.     va_start(args);
  1058. #else
  1059.     args = 0;
  1060. #endif
  1061.     message = mess(args);
  1062.     va_end(args);
  1063.     if (in_eval) {
  1064.     str_set(stab_val(stabent("@",TRUE)),message);
  1065.     tmps = "_EVAL_";
  1066.     while (loop_ptr >= 0 && (!loop_stack[loop_ptr].loop_label ||
  1067.       strNE(tmps,loop_stack[loop_ptr].loop_label) )) {
  1068. #ifdef DEBUGGING
  1069.         if (debug & 4) {
  1070.         deb("(Skipping label #%d %s)\n",loop_ptr,
  1071.             loop_stack[loop_ptr].loop_label);
  1072.         }
  1073. #endif
  1074.         loop_ptr--;
  1075.     }
  1076. #ifdef DEBUGGING
  1077.     if (debug & 4) {
  1078.         deb("(Found label #%d %s)\n",loop_ptr,
  1079.         loop_stack[loop_ptr].loop_label);
  1080.     }
  1081. #endif
  1082.     if (loop_ptr < 0) {
  1083.         in_eval = 0;
  1084.         fatal("Bad label: %s", tmps);
  1085.     }
  1086.     longjmp(loop_stack[loop_ptr].loop_env, 1);
  1087.     }
  1088.     fputs(message,stderr);
  1089.     (void)fflush(stderr);
  1090.     if (e_fp)
  1091.     (void)UNLINK(e_tmpname);
  1092.     statusvalue >>= 8;
  1093.     exit((int)((errno&255)?errno:((statusvalue&255)?statusvalue:255)));
  1094. }
  1095.  
  1096. /*VARARGS0*/
  1097. warn(va_alist)
  1098. va_dcl
  1099. {
  1100.     va_list args;
  1101.     char *message;
  1102.  
  1103. #ifndef lint
  1104.     va_start(args);
  1105. #else
  1106.     args = 0;
  1107. #endif
  1108.     message = mess(args);
  1109.     va_end(args);
  1110.  
  1111.     fputs(message,stderr);
  1112. #ifdef LEAKTEST
  1113. #ifdef DEBUGGING
  1114.     if (debug & 4096)
  1115.     xstat();
  1116. #endif
  1117. #endif
  1118.     (void)fflush(stderr);
  1119. }
  1120. #endif
  1121.  
  1122. void
  1123. setenv(nam,val)
  1124. char *nam, *val;
  1125. {
  1126.     register int i=envix(nam);        /* where does it go? */
  1127.  
  1128.     if (environ == origenviron) {    /* need we copy environment? */
  1129.     int j;
  1130.     int max;
  1131.     char **tmpenv;
  1132.  
  1133.     /*SUPPRESS 530*/
  1134.     for (max = i; environ[max]; max++) ;
  1135.     New(901,tmpenv, max+2, char*);
  1136.     for (j=0; j<max; j++)        /* copy environment */
  1137.         tmpenv[j] = savestr(environ[j]);
  1138.     tmpenv[max] = Nullch;
  1139.     environ = tmpenv;        /* tell exec where it is now */
  1140.     }
  1141.     if (!val) {
  1142.     while (environ[i]) {
  1143.         environ[i] = environ[i+1];
  1144.         i++;
  1145.     }
  1146.     return;
  1147.     }
  1148.     if (!environ[i]) {            /* does not exist yet */
  1149.     Renew(environ, i+2, char*);    /* just expand it a bit */
  1150.     environ[i+1] = Nullch;    /* make sure it's null terminated */
  1151.     }
  1152.     else
  1153.     Safefree(environ[i]);
  1154.     New(904, environ[i], strlen(nam) + strlen(val) + 2, char);
  1155. #ifndef MSDOS
  1156.     (void)sprintf(environ[i],"%s=%s",nam,val);/* all that work just for this */
  1157. #else
  1158.     /* MS-DOS requires environment variable names to be in uppercase */
  1159.     /* [Tom Dinger, 27 August 1990: Well, it doesn't _require_ it, but
  1160.      * some utilities and applications may break because they only look
  1161.      * for upper case strings. (Fixed strupr() bug here.)]
  1162.      */
  1163.     strcpy(environ[i],nam); strupr(environ[i]);
  1164.     (void)sprintf(environ[i] + strlen(nam),"=%s",val);
  1165. #endif /* MSDOS */
  1166. }
  1167.  
  1168. int
  1169. envix(nam)
  1170. char *nam;
  1171. {
  1172.     register int i, len = strlen(nam);
  1173.  
  1174.     for (i = 0; environ[i]; i++) {
  1175.     if (strnEQ(environ[i],nam,len) && environ[i][len] == '=')
  1176.         break;            /* strnEQ must come first to avoid */
  1177.     }                    /* potential SEGV's */
  1178.     return i;
  1179. }
  1180.  
  1181. #ifdef EUNICE
  1182. unlnk(f)    /* unlink all versions of a file */
  1183. char *f;
  1184. {
  1185.     int i;
  1186.  
  1187.     for (i = 0; unlink(f) >= 0; i++) ;
  1188.     return i ? 0 : -1;
  1189. }
  1190. #endif
  1191.  
  1192. #ifndef HAS_MEMCPY
  1193. #ifndef HAS_BCOPY
  1194. char *
  1195. bcopy(from,to,len)
  1196. register char *from;
  1197. register char *to;
  1198. register int len;
  1199. {
  1200.     char *retval = to;
  1201.  
  1202.     while (len--)
  1203.     *to++ = *from++;
  1204.     return retval;
  1205. }
  1206. #endif
  1207.  
  1208. #ifndef HAS_BZERO
  1209. char *
  1210. bzero(loc,len)
  1211. register char *loc;
  1212. register int len;
  1213. {
  1214.     char *retval = loc;
  1215.  
  1216.     while (len--)
  1217.     *loc++ = 0;
  1218.     return retval;
  1219. }
  1220. #endif
  1221. #endif
  1222.  
  1223. #ifdef I_VARARGS
  1224. #ifndef HAS_VPRINTF
  1225.  
  1226. #ifdef CHARVSPRINTF
  1227. char *
  1228. #else
  1229. int
  1230. #endif
  1231. vsprintf(dest, pat, args)
  1232. char *dest, *pat, *args;
  1233. {
  1234.     FILE fakebuf;
  1235.  
  1236.     fakebuf._ptr = dest;
  1237.     fakebuf._cnt = 32767;
  1238. #ifndef _IOSTRG
  1239. #define _IOSTRG 0
  1240. #endif
  1241.     fakebuf._flag = _IOWRT|_IOSTRG;
  1242.     _doprnt(pat, args, &fakebuf);    /* what a kludge */
  1243.     (void)putc('\0', &fakebuf);
  1244. #ifdef CHARVSPRINTF
  1245.     return(dest);
  1246. #else
  1247.     return 0;        /* perl doesn't use return value */
  1248. #endif
  1249. }
  1250.  
  1251. #ifdef DEBUGGING
  1252. int
  1253. vfprintf(fd, pat, args)
  1254. FILE *fd;
  1255. char *pat, *args;
  1256. {
  1257.     _doprnt(pat, args, fd);
  1258.     return 0;        /* wrong, but perl doesn't use the return value */
  1259. }
  1260. #endif
  1261. #endif /* HAS_VPRINTF */
  1262. #endif /* I_VARARGS */
  1263.  
  1264. /*
  1265.  * I think my_swap(), htonl() and ntohl() have never been used.
  1266.  * perl.h contains last-chance references to my_swap(), my_htonl()
  1267.  * and my_ntohl().  I presume these are the intended functions;
  1268.  * but htonl() and ntohl() have the wrong names.  There are no
  1269.  * functions my_htonl() and my_ntohl() defined anywhere.
  1270.  * -DWS
  1271.  */
  1272. #ifdef MYSWAP
  1273. #if BYTEORDER != 0x4321
  1274. short
  1275. my_swap(s)
  1276. short s;
  1277. {
  1278. #if (BYTEORDER & 1) == 0
  1279.     short result;
  1280.  
  1281.     result = ((s & 255) << 8) + ((s >> 8) & 255);
  1282.     return result;
  1283. #else
  1284.     return s;
  1285. #endif
  1286. }
  1287.  
  1288. long
  1289. htonl(l)
  1290. register long l;
  1291. {
  1292.     union {
  1293.     long result;
  1294.     char c[sizeof(long)];
  1295.     } u;
  1296.  
  1297. #if BYTEORDER == 0x1234
  1298.     u.c[0] = (l >> 24) & 255;
  1299.     u.c[1] = (l >> 16) & 255;
  1300.     u.c[2] = (l >> 8) & 255;
  1301.     u.c[3] = l & 255;
  1302.     return u.result;
  1303. #else
  1304. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1305.     fatal("Unknown BYTEORDER\n");
  1306. #else
  1307.     register int o;
  1308.     register int s;
  1309.  
  1310.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1311.     u.c[o & 0xf] = (l >> s) & 255;
  1312.     }
  1313.     return u.result;
  1314. #endif
  1315. #endif
  1316. }
  1317.  
  1318. long
  1319. ntohl(l)
  1320. register long l;
  1321. {
  1322.     union {
  1323.     long l;
  1324.     char c[sizeof(long)];
  1325.     } u;
  1326.  
  1327. #if BYTEORDER == 0x1234
  1328.     u.c[0] = (l >> 24) & 255;
  1329.     u.c[1] = (l >> 16) & 255;
  1330.     u.c[2] = (l >> 8) & 255;
  1331.     u.c[3] = l & 255;
  1332.     return u.l;
  1333. #else
  1334. #if ((BYTEORDER - 0x1111) & 0x444) || !(BYTEORDER & 0xf)
  1335.     fatal("Unknown BYTEORDER\n");
  1336. #else
  1337.     register int o;
  1338.     register int s;
  1339.  
  1340.     u.l = l;
  1341.     l = 0;
  1342.     for (o = BYTEORDER - 0x1111, s = 0; s < (sizeof(long)*8); o >>= 4, s += 8) {
  1343.     l |= (u.c[o & 0xf] & 255) << s;
  1344.     }
  1345.     return l;
  1346. #endif
  1347. #endif
  1348. }
  1349.  
  1350. #endif /* BYTEORDER != 0x4321 */
  1351. #endif /* MYSWAP */
  1352.  
  1353. /*
  1354.  * Little-endian byte order functions - 'v' for 'VAX', or 'reVerse'.
  1355.  * If these functions are defined,
  1356.  * the BYTEORDER is neither 0x1234 nor 0x4321.
  1357.  * However, this is not assumed.
  1358.  * -DWS
  1359.  */
  1360.  
  1361. #define HTOV(name,type)                        \
  1362.     type                            \
  1363.     name (n)                        \
  1364.     register type n;                    \
  1365.     {                            \
  1366.         union {                        \
  1367.         type value;                    \
  1368.         char c[sizeof(type)];                \
  1369.         } u;                        \
  1370.         register int i;                    \
  1371.         register int s;                    \
  1372.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1373.         u.c[i] = (n >> s) & 0xFF;            \
  1374.         }                            \
  1375.         return u.value;                    \
  1376.     }
  1377.  
  1378. #define VTOH(name,type)                        \
  1379.     type                            \
  1380.     name (n)                        \
  1381.     register type n;                    \
  1382.     {                            \
  1383.         union {                        \
  1384.         type value;                    \
  1385.         char c[sizeof(type)];                \
  1386.         } u;                        \
  1387.         register int i;                    \
  1388.         register int s;                    \
  1389.         u.value = n;                    \
  1390.         n = 0;                        \
  1391.         for (i = 0, s = 0; i < sizeof(u.c); i++, s += 8) {    \
  1392.         n += (u.c[i] & 0xFF) << s;            \
  1393.         }                            \
  1394.         return n;                        \
  1395.     }
  1396.  
  1397. #if defined(HAS_HTOVS) && !defined(htovs)
  1398. HTOV(htovs,short)
  1399. #endif
  1400. #if defined(HAS_HTOVL) && !defined(htovl)
  1401. HTOV(htovl,long)
  1402. #endif
  1403. #if defined(HAS_VTOHS) && !defined(vtohs)
  1404. VTOH(vtohs,short)
  1405. #endif
  1406. #if defined(HAS_VTOHL) && !defined(vtohl)
  1407. VTOH(vtohl,long)
  1408. #endif
  1409.  
  1410. #ifndef MSMAC
  1411. FILE *
  1412. mypopen(cmd,mode)
  1413. char    *cmd;
  1414. char    *mode;
  1415. {
  1416.     int p[2];
  1417.     register int this, that;
  1418.     register int pid;
  1419.     STR *str;
  1420.     int doexec = strNE(cmd,"-");
  1421.  
  1422.     if (pipe(p) < 0)
  1423.     return Nullfp;
  1424.     this = (*mode == 'w');
  1425.     that = !this;
  1426. #ifdef TAINT
  1427.     if (doexec) {
  1428.     taintenv();
  1429.     taintproper("Insecure dependency in exec");
  1430.     }
  1431. #endif
  1432.     while ((pid = (doexec?vfork():fork())) < 0) {
  1433.     if (errno != EAGAIN) {
  1434.         close(p[this]);
  1435.         if (!doexec)
  1436.         fatal("Can't fork");
  1437.         return Nullfp;
  1438.     }
  1439.     sleep(5);
  1440.     }
  1441.     if (pid == 0) {
  1442. #define THIS that
  1443. #define THAT this
  1444.     close(p[THAT]);
  1445.     if (p[THIS] != (*mode == 'r')) {
  1446.         dup2(p[THIS], *mode == 'r');
  1447.         close(p[THIS]);
  1448.     }
  1449.     if (doexec) {
  1450. #if !defined(HAS_FCNTL) || !defined(F_SETFD)
  1451.         int fd;
  1452.  
  1453. #ifndef NOFILE
  1454. #define NOFILE 20
  1455. #endif
  1456.         for (fd = maxsysfd + 1; fd < NOFILE; fd++)
  1457.         close(fd);
  1458. #endif
  1459.         do_exec(cmd);    /* may or may not use the shell */
  1460.         warn("Can't exec \"%s\": %s", cmd, strerror(errno));
  1461.         _exit(1);
  1462.     }
  1463.     /*SUPPRESS 560*/
  1464.     if (tmpstab = stabent("$",allstabs))
  1465.         str_numset(STAB_STR(tmpstab),(double)getpid());
  1466.     forkprocess = 0;
  1467.     hclear(pidstatus, FALSE);    /* we have no children */
  1468.     return Nullfp;
  1469. #undef THIS
  1470. #undef THAT
  1471.     }
  1472.     do_execfree();    /* free any memory malloced by child on vfork */
  1473.     close(p[that]);
  1474.     if (p[that] < p[this]) {
  1475.     dup2(p[this], p[that]);
  1476.     close(p[this]);
  1477.     p[this] = p[that];
  1478.     }
  1479.     str = afetch(fdpid,p[this],TRUE);
  1480.     str->str_u.str_useful = pid;
  1481.     forkprocess = pid;
  1482.     return fdopen(p[this], mode);
  1483. }
  1484. #endif /* !MSMAC */
  1485.  
  1486. #ifdef NOTDEF
  1487. dumpfds(s)
  1488. char *s;
  1489. {
  1490.     int fd;
  1491.     struct stat tmpstatbuf;
  1492.  
  1493.     fprintf(stderr,"%s", s);
  1494.     for (fd = 0; fd < 32; fd++) {
  1495.     if (fstat(fd,&tmpstatbuf) >= 0)
  1496.         fprintf(stderr," %d",fd);
  1497.     }
  1498.     fprintf(stderr,"\n");
  1499. }
  1500. #endif
  1501.  
  1502. #ifndef HAS_DUP2
  1503. dup2(oldfd,newfd)
  1504. int oldfd;
  1505. int newfd;
  1506. {
  1507. #if defined(HAS_FCNTL) && defined(F_DUPFD)
  1508.     close(newfd);
  1509.     fcntl(oldfd, F_DUPFD, newfd);
  1510. #else
  1511.     int fdtmp[256];
  1512.     int fdx = 0;
  1513.     int fd;
  1514.  
  1515.     if (oldfd == newfd)
  1516.     return 0;
  1517.     close(newfd);
  1518.     while ((fd = dup(oldfd)) != newfd)    /* good enough for low fd's */
  1519.     fdtmp[fdx++] = fd;
  1520.     while (fdx > 0)
  1521.     close(fdtmp[--fdx]);
  1522. #endif
  1523. }
  1524. #endif
  1525.  
  1526. #ifndef MSMAC
  1527. int
  1528. mypclose(ptr)
  1529. FILE *ptr;
  1530. {
  1531. #ifdef VOIDSIG
  1532.     void (*hstat)(), (*istat)(), (*qstat)();
  1533. #else
  1534.     int (*hstat)(), (*istat)(), (*qstat)();
  1535. #endif
  1536.     int status;
  1537.     STR *str;
  1538.     int pid;
  1539.  
  1540.     str = afetch(fdpid,fileno(ptr),TRUE);
  1541.     pid = (int)str->str_u.str_useful;
  1542.     astore(fdpid,fileno(ptr),Nullstr);
  1543.     fclose(ptr);
  1544.     hstat = signal(SIGHUP, SIG_IGN);
  1545.     istat = signal(SIGINT, SIG_IGN);
  1546.     qstat = signal(SIGQUIT, SIG_IGN);
  1547.     pid = wait4pid(pid, &status, 0);
  1548.     signal(SIGHUP, hstat);
  1549.     signal(SIGINT, istat);
  1550.     signal(SIGQUIT, qstat);
  1551.     return(pid < 0 ? pid : status);
  1552. }
  1553.  
  1554. int
  1555. wait4pid(pid,statusp,flags)
  1556. int pid;
  1557. int *statusp;
  1558. int flags;
  1559. {
  1560. #if !defined(HAS_WAIT4) && !defined(HAS_WAITPID)
  1561.     int result;
  1562.     STR *str;
  1563.     char spid[16];
  1564. #endif
  1565.  
  1566.     if (!pid)
  1567.     return -1;
  1568. #ifdef HAS_WAIT4
  1569.     return wait4((pid==-1)?0:pid,statusp,flags,Null(struct rusage *));
  1570. #else
  1571. #ifdef HAS_WAITPID
  1572.     return waitpid(pid,statusp,flags);
  1573. #else
  1574.     if (pid > 0) {
  1575.     sprintf(spid, "%d", pid);
  1576.     str = hfetch(pidstatus,spid,strlen(spid),FALSE);
  1577.     if (str != &str_undef) {
  1578.         *statusp = (int)str->str_u.str_useful;
  1579.         hdelete(pidstatus,spid,strlen(spid));
  1580.         return pid;
  1581.     }
  1582.     }
  1583.     else {
  1584.     HENT *entry;
  1585.  
  1586.     hiterinit(pidstatus);
  1587.     if (entry = hiternext(pidstatus)) {
  1588.         pid = atoi(hiterkey(entry,statusp));
  1589.         str = hiterval(entry);
  1590.         *statusp = (int)str->str_u.str_useful;
  1591.         sprintf(spid, "%d", pid);
  1592.         hdelete(pidstatus,spid,strlen(spid));
  1593.         return pid;
  1594.     }
  1595.     }
  1596.     if (flags)
  1597.     fatal("Can't do waitpid with flags");
  1598.     else {
  1599.     while ((result = wait(statusp)) != pid && pid > 0 && result >= 0)
  1600.         pidgone(result,*statusp);
  1601.     if (result < 0)
  1602.         *statusp = -1;
  1603.     }
  1604.     return result;
  1605. #endif
  1606. #endif
  1607. }
  1608.  
  1609. /*SUPPRESS 590*/
  1610. pidgone(pid,status)
  1611. int pid;
  1612. int status;
  1613. {
  1614. #if defined(HAS_WAIT4) || defined(HAS_WAITPID)
  1615. #else
  1616.     register STR *str;
  1617.     char spid[16];
  1618.  
  1619.     sprintf(spid, "%d", pid);
  1620.     str = hfetch(pidstatus,spid,strlen(spid),TRUE);
  1621.     str->str_u.str_useful = status;
  1622. #endif
  1623.     return;
  1624. }
  1625. #endif /* !MSMAC */
  1626.  
  1627. #ifndef HAS_MEMCMP
  1628. memcmp(s1,s2,len)
  1629. register unsigned char *s1;
  1630. register unsigned char *s2;
  1631. register int len;
  1632. {
  1633.     register int tmp;
  1634.  
  1635.     while (len--) {
  1636.     if (tmp = *s1++ - *s2++)
  1637.         return tmp;
  1638.     }
  1639.     return 0;
  1640. }
  1641. #endif /* HAS_MEMCMP */
  1642.  
  1643. void
  1644. repeatcpy(to,from,len,count)
  1645. register char *to;
  1646. register char *from;
  1647. int len;
  1648. register int count;
  1649. {
  1650.     register int todo;
  1651.     register char *frombase = from;
  1652.  
  1653.     if (len == 1) {
  1654.     todo = *from;
  1655.     while (count-- > 0)
  1656.         *to++ = todo;
  1657.     return;
  1658.     }
  1659.     while (count-- > 0) {
  1660.     for (todo = len; todo > 0; todo--) {
  1661.         *to++ = *from++;
  1662.     }
  1663.     from = frombase;
  1664.     }
  1665. }
  1666.  
  1667. #ifndef CASTNEGFLOAT
  1668. unsigned long
  1669. castulong(f)
  1670. double f;
  1671. {
  1672.     long along;
  1673.  
  1674. #if CASTFLAGS & 2
  1675. #   define BIGDOUBLE 2147483648.0
  1676.     if (f >= BIGDOUBLE)
  1677.     return (unsigned long)(f-(long)(f/BIGDOUBLE)*BIGDOUBLE)|0x80000000;
  1678. #endif
  1679.     if (f >= 0.0)
  1680.     return (unsigned long)f;
  1681.     along = (long)f;
  1682.     return (unsigned long)along;
  1683. }
  1684. #endif
  1685.  
  1686. #ifndef HAS_RENAME
  1687. int
  1688. same_dirent(a,b)
  1689. char *a;
  1690. char *b;
  1691. {
  1692.     char *fa = rindex(a,'/');
  1693.     char *fb = rindex(b,'/');
  1694.     struct stat tmpstatbuf1;
  1695.     struct stat tmpstatbuf2;
  1696. #ifndef MAXPATHLEN
  1697. #define MAXPATHLEN 1024
  1698. #endif
  1699.     char tmpbuf[MAXPATHLEN+1];
  1700.  
  1701.     if (fa)
  1702.     fa++;
  1703.     else
  1704.     fa = a;
  1705.     if (fb)
  1706.     fb++;
  1707.     else
  1708.     fb = b;
  1709.     if (strNE(a,b))
  1710.     return FALSE;
  1711.     if (fa == a)
  1712.     strcpy(tmpbuf,".");
  1713.     else
  1714.     strncpy(tmpbuf, a, fa - a);
  1715.     if (stat(tmpbuf, &tmpstatbuf1) < 0)
  1716.     return FALSE;
  1717.     if (fb == b)
  1718.     strcpy(tmpbuf,".");
  1719.     else
  1720.     strncpy(tmpbuf, b, fb - b);
  1721.     if (stat(tmpbuf, &tmpstatbuf2) < 0)
  1722.     return FALSE;
  1723.     return tmpstatbuf1.st_dev == tmpstatbuf2.st_dev &&
  1724.        tmpstatbuf1.st_ino == tmpstatbuf2.st_ino;
  1725. }
  1726. #endif /* !HAS_RENAME */
  1727.  
  1728. unsigned long
  1729. scanoct(start, len, retlen)
  1730. char *start;
  1731. int len;
  1732. int *retlen;
  1733. {
  1734.     register char *s = start;
  1735.     register unsigned long retval = 0;
  1736.  
  1737.     while (len-- && *s >= '0' && *s <= '7') {
  1738.     retval <<= 3;
  1739.     retval |= *s++ - '0';
  1740.     }
  1741.     *retlen = s - start;
  1742.     return retval;
  1743. }
  1744.  
  1745. unsigned long
  1746. scanhex(start, len, retlen)
  1747. char *start;
  1748. int len;
  1749. int *retlen;
  1750. {
  1751.     register char *s = start;
  1752.     register unsigned long retval = 0;
  1753.     char *tmp;
  1754.  
  1755.     while (len-- && *s && (tmp = index(hexdigit, *s))) {
  1756.     retval <<= 4;
  1757.     retval |= (tmp - hexdigit) & 15;
  1758.     s++;
  1759.     }
  1760.     *retlen = s - start;
  1761.     return retval;
  1762. }
  1763.